
package org.jarfinder;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import javax.swing.JOptionPane;

public class JarFinderUtil {

    private boolean caseSensitive = false;
    private boolean matchPackage = false;
    private boolean exactMatch = false;
    private boolean searchForClass = true;
    private boolean searchInJar = true;
    private boolean searchInZip = true;
    private boolean searchInOther = false;
    private String otherToSearchIn = null;
    private int numFilesTotal = 0;
    private int numFiles = 0;

    /** The jar finder. */
    JarFinder jarFinder = null;

    /** The index. */
    int index = 0;

    /**
     * Update progress.
     * 
     * @param index
     *            the index
     * @param maxSize
     *            the max size
     */
    private void updateProgress(int index) {

	if (this.numFilesTotal > 0) {

	    int value = (index * 100) / this.numFilesTotal;

	    // jarFinder.progressBar.setValue(value);
	    // jarFinder.progressBar.repaint();
	}
    }

    /**
     * Find jar.
     * 
     * @param jarDirectory
     *            the jar directory
     * @param className
     *            the class name
     * @param jarFinder
     *            the jar finder
     * 
     * @return the sets the
     */
    public void findJar(String jarDirectory, String className, JarFinder jarFinder) {
	this.jarFinder = jarFinder;
	       

	if ((jarDirectory != null) && (className != null) && (className.trim().length() > 0)) {
	    jarFinder.updateStatus(jarFinder.STATUS_STARTED);

	    // jarFinder.progressBar.setValue(0);
	    jarFinder.progressBar.setVisible(true);

	    index = 0;

	    File file = new File(jarDirectory);
	    if (file.isFile() && !className.equals(""))
		searchJarForClass(className, file);
	    else if (file.isDirectory() && !className.equals("")) {
		File files[] = file.listFiles();
		if (files != null)
		    this.numFilesTotal = files.length;
		// monitor.beginTask("Searching Classes...", files.length);
		enumerateContents(className, file);
	    }
	    
	    jarFinder.updateStatus(jarFinder.STATUS_COMPLETED);

	} else {
	    JOptionPane.showMessageDialog(jarFinder, "Please specify the " + "directory and fully qualified class name.", "Error", JOptionPane.ERROR_MESSAGE);
	    jarFinder.updateStatus(jarFinder.STATUS_ERROR);
	}

    }

    private void enumerateContents(String className, File file) {
	File files[] = file.listFiles();
	if (files == null)
	    return;
	numFilesTotal += file.length();
	for (int i = 0; i < files.length; i++) {
	    numFiles++;
	    updateProgress(numFiles);
	    file = files[i];
	    if (file.isFile()
		    && (searchInJar && file.getName().endsWith(".jar") || searchInZip && file.getName().endsWith(".zip") || searchInOther
			    && file.getName().endsWith(otherToSearchIn)))
		searchJarForClass(className, file);
	    else if (file.isDirectory())
		enumerateContents(className, file);
	}

    }

    private void searchJarForClass(String className, File file) {
	String classNameCased = null;
	if (caseSensitive)
	    classNameCased = className;
	else
	    classNameCased = className.toLowerCase();
	try {
	    ZipFile zipFile = new ZipFile(file);
	    this.numFilesTotal += zipFile.size();

	    for (Enumeration enumeration = zipFile.entries(); enumeration.hasMoreElements();) {
		// numFiles++;
		String fileName = enumeration.nextElement().toString();
		if ((searchForClass && fileName.toLowerCase().endsWith(".class") || !searchForClass && fileName.toLowerCase().endsWith(".properties"))
			&& fileName.indexOf('$') < 0) {
		    String testClassName = null;
		    if (matchPackage)
			testClassName = fileName.replace('/', '.').substring(0, fileName.lastIndexOf('.'));
		    else
			testClassName = fileName.substring(fileName.lastIndexOf('/') + 1, fileName.lastIndexOf('.'));
		    if (!caseSensitive)
			testClassName = testClassName.toLowerCase();
		    if (exactMatch) {
			if (testClassName.equals(classNameCased))
			    addFound(fileName, zipFile);
		    } else if (testClassName.indexOf(classNameCased) >= 0)
			addFound(fileName, zipFile);
		}
		updateProgress(numFiles);
	    }

	} catch (ZipException _ex) {
	} catch (IOException _ex) {
	}
    }

    private void addFound(String className, ZipFile zipFile) {
	index++;
	SearchResult result = new SearchResult();
	result.setRowNo(new Integer(index));
	result.setFileName(zipFile.getName());
	result.setClassName(className);
	jarFinder.getResultsTableModel().updateData(result);
    }

    public boolean isCaseSensitive() {
        return caseSensitive;
    }

    public void setCaseSensitive(boolean caseSensitive) {
        this.caseSensitive = caseSensitive;
    }

    public boolean isMatchPackage() {
        return matchPackage;
    }

    public void setMatchPackage(boolean matchPackage) {
        this.matchPackage = matchPackage;
    }

    public boolean isExactMatch() {
        return exactMatch;
    }

    public void setExactMatch(boolean exactMatch) {
        this.exactMatch = exactMatch;
    }

    public boolean isSearchForClass() {
        return searchForClass;
    }

    public void setSearchForClass(boolean searchForClass) {
        this.searchForClass = searchForClass;
    }

    public boolean isSearchInJar() {
        return searchInJar;
    }

    public void setSearchInJar(boolean searchInJar) {
        this.searchInJar = searchInJar;
    }

    public boolean isSearchInZip() {
        return searchInZip;
    }

    public void setSearchInZip(boolean searchInZip) {
        this.searchInZip = searchInZip;
    }

    public boolean isSearchInOther() {
        return searchInOther;
    }

    public void setSearchInOther(boolean searchInOther) {
        this.searchInOther = searchInOther;
    }

}
